﻿using Microsoft.Win32.SafeHandles;
using System;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;


namespace CSharpWheels.Librarys.Dump
{
    //回调函数的实际应用场景
    //进度监控：通过 IoStartCallback, IoWriteAllCallback, IoFinishCallback 可以监控转储文件的写入进度。
    public class DumpProgressMonitor : MiniDump
    {
        // 定义回调相关结构
        [StructLayout(LayoutKind.Sequential)]
        public struct MINIDUMP_CALLBACK_INFORMATION
        {
            public MiniDumpCallbackRoutine CallbackRoutine;
            public IntPtr CallbackParam;
        }

        [StructLayout(LayoutKind.Explicit)]
        public struct MINIDUMP_CALLBACK_INPUT
        {
            [FieldOffset(0)] public uint ProcessId;
            [FieldOffset(4)] public IntPtr ProcessHandle;
            [FieldOffset(8)] public uint CallbackType;
            [FieldOffset(12)] public IntPtr CallbackInfo;
        }

        [StructLayout(LayoutKind.Explicit)]
        public struct MINIDUMP_CALLBACK_OUTPUT
        {
            [FieldOffset(0)] public int Status;
        }

        // I/O 进度回调信息
        [StructLayout(LayoutKind.Sequential)]
        public struct MINIDUMP_IO_CALLBACK
        {
            public IntPtr Handle;
            public ulong Offset;
            public IntPtr Buffer;
            public uint BufferBytes;
        }

        public delegate bool MiniDumpCallbackRoutine(
            IntPtr CallbackParam,
            ref MINIDUMP_CALLBACK_INPUT CallbackInput,
            ref MINIDUMP_CALLBACK_OUTPUT CallbackOutput);


        // 进度报告事件
        public event Action<string, float> ProgressChanged;

        private long _totalBytesWritten;
        private long _estimatedTotalSize;

        public void CreateDumpWithProgress(string dumpFilePath, uint dumpType)
        {
            _totalBytesWritten = 0;
            _estimatedTotalSize = EstimateDumpSize();

            var callbackInfo = new MINIDUMP_CALLBACK_INFORMATION
            {
                CallbackRoutine = DumpProgressCallback,
                CallbackParam = IntPtr.Zero
            };

            int size = Marshal.SizeOf(callbackInfo);
            IntPtr callbackInfoPtr = Marshal.AllocHGlobal(size);
            Marshal.StructureToPtr(callbackInfo, callbackInfoPtr, false);

            try
            {
                using (var fs = new FileStream(dumpFilePath, FileMode.Create))
                {
                    var currentProcess = Process.GetCurrentProcess();
                    bool success = MiniDumpWriteDump(
                        currentProcess.Handle,
                        (uint)currentProcess.Id,
                        fs.SafeFileHandle,
                        dumpType,
                        IntPtr.Zero,
                        IntPtr.Zero,
                        callbackInfoPtr);

                    if (!success)
                    {
                        throw new System.ComponentModel.Win32Exception(
                            Marshal.GetLastWin32Error());
                    }
                }
            }
            finally
            {
                Marshal.FreeHGlobal(callbackInfoPtr);
            }
        }

        private long EstimateDumpSize()
        {
            // 简单估算 - 实际应用中可以根据进程内存使用情况更精确估算
            var process = Process.GetCurrentProcess();
            return process.WorkingSet64 / 2; // 通常转储文件比工作集小
        }

        private bool DumpProgressCallback(
            IntPtr callbackParam,
            ref MINIDUMP_CALLBACK_INPUT callbackInput,
            ref MINIDUMP_CALLBACK_OUTPUT callbackOutput)
        {

            if (callbackInput.CallbackType == (uint)MINIDUMP_CALLBACK_TYPE.IoWriteAllCallback)
            {
                var ioInfo = Marshal.PtrToStructure<MINIDUMP_IO_CALLBACK>(
                    callbackInput.CallbackInfo);

                _totalBytesWritten += ioInfo.BufferBytes;

                float progress = _estimatedTotalSize > 0
                    ? Math.Min(100f, _totalBytesWritten * 100f / _estimatedTotalSize)
                    : 0;

                ProgressChanged?.Invoke(
                    $"写入转储数据: {_totalBytesWritten / 1024}KB",
                    progress);
            }
            else if (callbackInput.CallbackType == (uint)MINIDUMP_CALLBACK_TYPE.IoStartCallback) // IoStartCallback
            {
                ProgressChanged?.Invoke("开始创建转储文件...", 0);
            }
            else if (callbackInput.CallbackType == (uint)MINIDUMP_CALLBACK_TYPE.IoFinishCallback) // IoFinishCallback
            {
                ProgressChanged?.Invoke("转储文件创建完成", 100);
            }

            return true;
        }
    }

    // 定义回调类型枚举
    public enum MINIDUMP_CALLBACK_TYPE : uint
    {
        ModuleCallback,
        ThreadCallback,
        ThreadExCallback,
        IncludeThreadCallback,
        IncludeModuleCallback,
        MemoryCallback,
        CancelCallback,
        WriteKernelMinidumpCallback,
        KernelMinidumpStatusCallback,
        RemoveMemoryCallback,
        IncludeVmRegionCallback,
        IoStartCallback,
        IoWriteAllCallback,
        IoFinishCallback,
        ReadMemoryFailureCallback,
        SecondaryFlagsCallback,
        IsProcessSnapshotCallback,
        VmStartCallback,
        VmQueryCallback,
        VmPreReadCallback,
    }
}




